package com.game.utils;

import java.net.InetSocketAddress;
import java.net.SocketAddress;

import javax.servlet.http.HttpServletRequest;


/**
 * IP相关操作工具类.
 *
 */
public class IpUtils {

	private static final int IP_LOOP_NUM = 3;
	private static final String LOCAL_IP = "127.0.0.1";
	/**
	 * 私有IP：
	 * <p>
	 * A类 10.0.0.0-10.255.255.255 <br>
	 * B类 172.16.0.0-172.31.255.255 <br>
	 * C类 192.168.0.0-192.168.255.255<br>
	 **/
	private static long A_BEGIN = ipToLong("10.0.0.0");
	private static long A_END = ipToLong("10.255.255.255");
	private static long B_BEGIN = ipToLong("172.16.0.0");
	private static long B_END = ipToLong("172.31.255.255");
	private static long C_BEGIN = ipToLong("192.168.0.0");
	private static long C_END = ipToLong("192.168.255.255");

	/**
	 * IP转化为Long类型的数字.
	 *
	 * @param ipAddress IP地址
	 * @return Long类型的数字
	 */
	public static long ipToLong(String ipAddress) {
		final String[] array = StringUtils.split(ipAddress, ".");
		long result = 0;
		for (int i = IP_LOOP_NUM; i >= 0; i--) {
			result |= Long.parseLong(array[3 - i]) << (i * 8);
		}
		return result;
	}

	/**
	 * 判定一个IP是否为内网IP.
	 * <p>
	 * 除了上面的IP还包含了127.0.0.1
	 *
	 * @param ipAddress IP地址
	 * @return 如果是则返回true, 否则返回false
	 */
	public static boolean isInnerIp(String ipAddress) {
		final long ipNum = ipToLong(ipAddress);
		return isInner(ipNum, A_BEGIN, A_END) || isInner(ipNum, B_BEGIN, B_END) || isInner(ipNum, C_BEGIN, C_END)
				|| LOCAL_IP.equals(ipAddress);
	}

	/**
	 * 判定一个IP地址在否在指定区间内.
	 *
	 * @param ipNum IP地址
	 * @param begin 指定区间开始值
	 * @param end   指定区间结束值
	 * @return 如果在区间内则返回true, 否则返回false
	 */
	private static boolean isInner(long ipNum, long begin, long end) {
		return (ipNum >= begin) && (ipNum <= end);
	}

	/**
	 * 获取套接字地址的IP
	 *
	 * @param address 套接字地址
	 * @return 返回目标IP
	 */
	public static String getIp(SocketAddress address) {
		return ((InetSocketAddress) address).getAddress().getHostAddress();
	}

	public static String getClientIp(HttpServletRequest request) {
		// X-Forwarded-For，不区分大小写
		String possibleIpStr = request.getHeader("X-Forwarded-For");
		String remoteIp = request.getRemoteAddr();
		String clientIp;
		if (StringUtils.isNotBlank(possibleIpStr) && !"unknown".equalsIgnoreCase(possibleIpStr)) {
			// 可能经过好几个转发流程，第一个是用户的真实ip，后面的是转发服务器的ip
			clientIp = possibleIpStr.split(",")[0].trim();
		} else {
			// 如果转发头ip为空，说明是直接访问的，没有经过转发
			clientIp = remoteIp;
		}
		return clientIp;
	}
}